import re
from datetime import datetime, timedelta
from qturboframe.lib.report.log import logger
from hslib.webdriver.data_change import (deal_datetime, deal_time)

from .base_element import BaseElement


class Calendar(BaseElement):
    '''
    jres2.0的日历控件

    :Attributes:
     - _driver: 控件所在的当前webdriver对象
     - _element: 控件元素webelement对象
     - timeout: 步骤操作的超时时间

    :Example:
     - 例1: Calendar(webelement)
     - 例2: Calendar({By.CLASS_NAME:'class_name','text':'文本信息'})
     - 例3: Calendar({By.CLASS_NAME:'class_name','text':'文本信息'}, father=driver)
     - 例4: Calendar({By.CLASS_NAME:'class_name','text':'文本信息'}, father=webelement)
    '''

    def __init__(self, element_para=None, father=None, timeout=5):
        super().__init__(element_para, father, timeout)


    def set_value(self, text):
        """
        jres2.0的日历框控件赋值

        :Args:
         - text: 日期值

        :Example:
         - 例1: calendar.set_value('20210219')
         - 例2: calendar.set_value('今天')
         - 例2: calendar.set_value('today')
        """
        re_displayblock = r'display:\s*block;*'
        re_days = r'datetimepicker-days'
        re_months = r'datetimepicker-months'
        re_years = r'datetimepicker-years'
        re_hours = r'datetimepicker-hours'
        re_minutes = r'datetimepicker-minutes'
        calendar_divs = self._element.find_elements_by_attribute('xpath', './div', timeout=self.timeout)
        if text == "明天":
            tomorrow = datetime.now() + timedelta(days=1)
            text = tomorrow.strftime("%Y%m%d")

        if text == '今天' or text.lower() == 'today':
            for calendar_div in calendar_divs:
                if re.search(re_displayblock, calendar_div.get_attribute('style')):
                    BaseElement(calendar_div).click()
        else:
            textlist = text.split(' ')
            if len(textlist) == 2:
                date = textlist[0]
                date = deal_datetime(date)
                year, month, day = date.split('/')
                time = textlist[1]
                time = deal_time(time)
                hour, minute, second = time.split(':')
            else:
                if ':' in textlist[0]:
                    time = textlist[0]
                    time = deal_time(time)
                    hour, minute, second = time.split(':')
                    year = None
                    month = None
                    day = None
                else:
                    date = textlist[0]
                    date = deal_datetime(date)
                    year, month, day = date.split('/')
                    hour = None
                    minute = None
                    second = None
            day_div = None
            month_div = None
            year_div = None
            hour_div = None
            minute_div = None
            for calendar_div in calendar_divs:
                div_class = calendar_div.get_attribute('class')
                if re.search(re_days, div_class):
                    day_div = calendar_div
                elif re.search(re_months, div_class):
                    month_div = calendar_div
                elif re.search(re_years, div_class):
                    year_div = calendar_div
                elif re.search(re_hours, div_class):
                    hour_div = calendar_div
                elif re.search(re_minutes, div_class):
                    minute_div = calendar_div
            # 切换到year_div
            for i in range(0, 6):
                if re.search(re_displayblock, day_div.get_attribute('style')):
                    BaseElement(day_div.find_element_by_attribute("xpath", "./table/thead/tr[1]/th[2]")).click()
                elif re.search(re_displayblock, month_div.get_attribute('style')):
                    BaseElement(month_div.find_element_by_attribute("xpath", "./table/thead/tr/th[2]")).click()
                elif re.search(re_displayblock, hour_div.get_attribute('style')):
                    # hour_div.find_element_by_attribute("xpath", "./table/thead/tr/th[2]")
                    BaseElement(hour_div.find_element_by_attribute("xpath", "./table/thead/tr/th[2]")).click()
                elif re.search(re_displayblock, minute_div.get_attribute('style')):
                    BaseElement(minute_div.find_element_by_attribute("xpath", "./table/thead/tr/th[2]")).click()
                elif re.search(re_displayblock, year_div.get_attribute('style')):
                    break
            # 选择year
            if re.search(re_displayblock, self._element.get_attribute('style')):
                year_div = self._element.find_element_by_attribute('class name', re_years, timeout=self.timeout)
                self.__set_year(year_div, year)
            # 选择month
            if re.search(re_displayblock, self._element.get_attribute('style')):
                month_div = self._element.find_element_by_attribute('class name', re_months, timeout=self.timeout)
                self.__set_month(month_div, month)
            # 选择day
            if re.search(re_displayblock, self._element.get_attribute('style')):
                day_div = self._element.find_element_by_attribute('class name', re_days, timeout=self.timeout)
                self.__set_day(day_div, day)
            # 选择hour
            if re.search(re_displayblock, self._element.get_attribute('style')):
                hour_div = self._element.find_element_by_attribute('class name', re_hours, timeout=self.timeout)
                self.__set_hour(hour_div, hour)
            # 选择minute
            if re.search(re_displayblock, self._element.get_attribute('style')):
                minute_div = self._element.find_element_by_attribute('class name', re_minutes, timeout=self.timeout)
                self.__set_minute(minute_div, hour, minute)

    def __set_year(self, year_div, year):
        text = year_div.find_element_by_attribute('xpath', './table/tbody').text
        textlist = re.findall(r'[^\n]+', text)
        if year not in textlist:
            if int(year) > int(textlist[-1]):
                # year_div.find_element_by_attribute('xpath', './table/thead/tr/th[3]').secure_click()
                BaseElement(year_div.find_element_by_attribute('xpath', './table/thead/tr/th[3]')).click()
                self.__set_year(year_div, year)
            elif int(year) < int(textlist[0]):
                # year_div.find_element_by_attribute('xpath', './table/thead/tr/th[1]').secure_click()
                BaseElement(year_div.find_element_by_attribute('xpath', './table/thead/tr/th[1]')).click()
                self.__set_year(year_div, year)
        else:
            span = year_div.find_element_by_attribute(
                'xpath', './table/tbody/tr/td/span[text()="' + year + '"]', timeout=self.timeout)
            BaseElement(span).click()

    def __set_month(self, month_div, month):
        # month_div.find_element_by_attribute('xpath', './table/tbody/tr/td/span[' + month + ']').secure_click()
        BaseElement(month_div.find_element_by_attribute('xpath', './table/tbody/tr/td/span[' + month + ']')).click()

    def __set_day(self, day_div, day):
        tds = day_div.find_elements_by_attribute(
            'xpath', './table/tbody/*/td[contains(@class,"day") and text()="' + str(int(day)) + '"]',
            timeout=self.timeout)
        for td in tds:
            td_class = td.get_attribute('class')
            if 'old' in td_class:
                continue
            elif 'new' in td_class:
                continue
            else:
                # td.secure_click()
                BaseElement(td).click()
                break

    def __set_hour(self, hour_div, hour):
        str_hour = str(int(hour)) + ':00'
        hour_span = hour_div.find_element_by_attribute('xpath', './/span[text()="' + str_hour + '"]',
                                                       timeout=self.timeout)
        # hour_span.secure_click()
        BaseElement(hour_span).click()

    def __set_minute(self, minute_div, hour, minute):
        str_minute = str(int(hour)) + ':' + str(int(minute))
        minute_span = minute_div.find_element_by_attribute(
            'xpath', './/span[text()="' + str_minute + '"]', timeout=self.timeout)
        # minute_span.secure_click()
        BaseElement(minute_span).click()

    def set_value_for_range(self, value):
        '''
        jres2.0的日历范围框控件赋值

        :Args:
         - value: 日期值

        :Example:
         - 例1: calendar.set_value_for_range('20210105,20210122')
         - 例2: calendar.set_value_for_range('今天')
         - 例3: calendar.set_value_for_range('today')
        '''
        re_ranges = r'ranges'
        re_left = r'left'
        re_right = r'right'
        text1 = value[0]
        if len(value) < 2:
            text2 = value[0]
        else:
            text2 = value[1]
        if text1 == '今天' or text1.lower() == 'today':
            ranges_div = self._element.find_element_by_attribute('xpath', './div', 'class:' + re_ranges,
                                                         timeout=self.timeout)
            # ranges_div.find_element_by_attribute('xpath:./ul/li').secure_click()
            BaseElement(ranges_div.find_element_by_attribute('xpath:./ul/li')).click()
        else:
            left_div = self._element.find_element_by_attribute('xpath', './div', 'class:' + re_left,
                                                       timeout=self.timeout)
            self.__set_date(left_div, text1)
            right_div = self._element.find_element_by_attribute('xpath', './div', 'class:' + re_right,
                                                        timeout=self.timeout)
            self.__set_date(right_div, text2)

    def __set_date(self, div, value):
        year, month, day = value.split('/')
        # 选择year
        self.__set_year_for_range(div, year)
        # 选择month
        self.__set_month_for_range(div, month)
        # 选择day
        self.__set_day_for_range(div, day)

    def __set_year_for_range(self, calendar_div, year):
        prev_class = r'prev'
        next_class = r'next'
        month_class = r'month'
        year_prev = r'fa-angle-double-left'
        year_next = r'fa-angle-double-right'
        while 1:
            month_th = calendar_div.find_element_by_attribute(
                'xpath', './div/table/thead/tr[1]/th', 'class:' + month_class, timeout=self.timeout)
            year_prev_li = calendar_div.find_element_by_attribute(
                'xpath', './div/table/thead/tr[1]/th[@class="' + prev_class + '"]/i',
                'class:' + year_prev, timeout=self.timeout)
            year_next_li = calendar_div.find_element_by_attribute(
                'xpath', './div/table/thead/tr[1]/th[@class="' + next_class + '"]/i',
                'class:' + year_next, timeout=self.timeout)
            year_text = month_th.text.split(' ')[1]
            if int(year) < int(year_text):
                # year_prev_li.secure_click()
                BaseElement(year_prev_li).click()
                self.__set_year_for_range(calendar_div, year)
            elif int(year) > int(year_text):
                # year_next_li.secure_click()
                BaseElement(year_next_li).click()
                self.__set_year_for_range(calendar_div, year)
            else:
                return

    def __set_month_for_range(self, calendar_div, month):
        month_prev = r'fa-angle-left'
        month_next = r'fa-angle-right'
        month_class = r'month'
        prev_class = r'prev'
        next_class = r'next'
        month_list = ['一月', '二月', '三月', '四月', '五月', '六月',
                      '七月', '八月', '九月', '十月', '十一月', '十二月', ]
        while 1:
            month_th = calendar_div.find_element_by_attribute(
                'xpath', './div/table/thead/tr[1]/th', 'class:' + month_class, timeout=self.timeout)
            month_prev_li = calendar_div.find_element_by_attribute(
                'xpath', './div/table/thead/tr[1]/th[@class="' + prev_class + '"]/i',
                'class:' + month_prev, timeout=self.timeout)
            month_next_li = calendar_div.find_element_by_attribute(
                'xpath', './div/table/thead/tr[1]/th[@class="' + next_class + '"]/i',
                'class:' + month_next, timeout=self.timeout)
            month_text = month_th.text.split(' ')[0]
            if int(month) < int(month_list.index(month_text) + 1):
                # month_prev_li.secure_click()
                BaseElement(month_prev_li).click()
                self.__set_month_for_range(calendar_div, month)
            elif int(month) > int(month_list.index(month_text) + 1):
                # month_next_li.secure_click()
                BaseElement(month_next_li).click()
                self.__set_month_for_range(calendar_div, month)
            else:
                return

    def __set_day_for_range(self, calendar_div, day):
        re_off = r'off'
        tds = calendar_div.find_elements_by_attribute(
            'xpath', './div/table/tbody/*/td[contains(@class,"available")]', timeout=self.timeout)
        for td in tds:
            if re.search(re_off, td.get_attribute('class')):
                continue
            if int(td.text) == int(day):
                # td.secure_click()
                BaseElement(td).click()
                return
        else:
            logger.getlogger().warn('未选中日期！')
    
    @staticmethod
    def is_readonly_for_group(self, inputs):
        """
        jres2.0的日历框组只读校验是否成功

        :Args:
         - inputs: 日历框控件组

        :Returns:
            控件组均是只读状态则返回True，否则返回False

        :Example:
         - 例: calendar.is_readonly_for_group()
        """
        for inputele in inputs:
            if not inputele.is_readonly():
                return False
        else:
            return True
    
    @staticmethod
    def is_default_for_group(self, inputs, value):
        """
        检查jres2.0的日历框组默认值

        :Args:
         - inputs: 日历框控件组
         - value: 待检查的一组值

        :Returns:
            检查所有都匹配返回True，否则返回False

        :Example:
         - 例: calendar.is_default_for_group()
        """
        value1 = value[0]
        if len(value) < 2:
            value2 = value[0]
        else:
            value2 = value[1]
        textlist = list()
        for inputele in inputs:
            inputele_hide = inputele.find_element_by_attribute('xpath', './preceding-sibling::input',
                                                               timeout=self.timeout)
            if inputele_hide.text:
                textlist.append(inputele_hide.text)
            elif inputele.get_attribute('value'):
                textlist.append(inputele.get_attribute('value'))
            elif inputele_hide.get_attribute('value'):
                textlist.append(inputele_hide.get_attribute('value'))
            elif inputele.get_attribute('placeholder'):
                textlist.append(inputele.get_attribute('placeholder'))
            else:
                textlist.append("")
        if textlist[0] == value1 and textlist[1] == value2:
            return True
        else:
            return False

    @staticmethod
    def is_default_for_range(self, inputele, value):
        """
        检查jres2.0的日历范围控件默认值

        :Args:
         - inputs: 日历范围框控件
         - value: 待检查的值

        :Returns:
            检查所有都匹配返回True，否则返回False

        :Example:
         - 例: calendar.is_default_for_range()
        """
        value1 = value[0]
        if len(value) < 2:
            value2 = value[0]
        else:
            value2 = value[1]
        text_flag = r' - '
        inputs_hide = inputele.find_element_by_attribute(
            'xpath', './preceding-sibling::input[@type=\'hidden\']', timeout=self.timeout)
        start_hide = inputs_hide[1]
        end_hide = inputs_hide[2]
        if inputele.text:
            text = inputele.text.split(text_flag)
        elif inputele.get_attribute('value'):
            text = inputele.get_attribute('value').split(text_flag)
        elif start_hide.get_attribute('value') and end_hide.get_attribute('value'):
            text = [start_hide.get_attribute('value'), end_hide.get_attribute('value')]
        elif inputele.get_attribute('placeholder'):
            text = inputele.get_attribute('placeholder').split(text_flag)
        else:
            text = []
        text1 = text[0]
        text2 = text[1]
        if text1 == value1 and text2 == value2:
            return True
        else:
            return False